#include "remotemail.h"
#include "byte_buffer.h"

as::md::RemoteMail::RemoteMail()
{

}

as::md::RemoteMail::RemoteMail(ByteBufferPtr &buf, const MailPos &from, const MailPos &to)
	:buf_(std::make_shared<ByteBuffer>()), from_(from), to_(to), mode_(BY_ADDR)
{
	buf_->make_writeable_bytes(buf->size() + 128);
	PackHeader(buf_);
	int canReadn = buf->ReadableBytes();
	buf_->write_uint16(canReadn);
	if(canReadn > 0)
		buf_->write_bytes(buf->GetReadPtr(), canReadn);
}



as::md::RemoteMail::RemoteMail(ByteBufferPtr &buf, const MailPos &from, const char *remoteName, int remoteFrameId)
	:buf_(std::make_shared<ByteBuffer>()), from_(from), mode_(BY_NAME)
{
	remote_actor_ = std::make_shared<RemoteActorName>();
	remote_actor_->frameworkId = remoteFrameId;
	remote_actor_->actorName = remoteName;
	
	buf_->make_writeable_bytes(buf->size() + 128);
	PackHeader(buf_);
	int canReadn = buf->ReadableBytes();
	buf_->write_uint16(canReadn);
	if(canReadn > 0)
		buf_->write_bytes(buf->GetReadPtr(), canReadn);
}

as::md::RemoteMail::~RemoteMail()
{

}

int as::md::RemoteMail::GetTargetAddrId()
{
	return mode_ == BY_ADDR ? to_.frame_id_ : remote_actor_->frameworkId;
}

int as::md::RemoteMail::Pack(ByteBufferPtr &buf)
{
	PackHeader(buf);
	buf->write_uint16(buf_->ReadableBytes());
	buf->write_bytes(buf_->GetReadPtr(), buf_->ReadableBytes());
	return 0;
}

int as::md::RemoteMail::PackHeader(ByteBufferPtr &buf)
{
	buf->write_uint8((uint8)mode_);
	if (mode_ == BY_ADDR)
	{
		WriteMailPos(buf, from_);
		WriteMailPos(buf, to_);
	}
	else
	{
		if (remote_actor_)
		{
			buf->write_string(remote_actor_->actorName);
			buf->write_int32(remote_actor_->frameworkId);
		}
		else
		{
			buf->write_string("");
			buf->write_int32(0);
		}
	}
	return 0;
}

int as::md::RemoteMail::UnPack(ByteBufferPtr &buf)
{
	uint8 mode = 0;
	buf->read_uint8(mode);
	mode_ = EMode(mode);
	if (mode == BY_ADDR)
	{
		ReadMailPos(buf, from_);
		ReadMailPos(buf, to_);
	}
	else
	{
		if (remote_actor_ == nullptr)
		{
			remote_actor_ = std::make_shared<RemoteActorName>();
		}

		buf->read_string(remote_actor_->actorName);
		buf->read_int32(remote_actor_->frameworkId);
	}

	uint16 bodyLen = 0;
	buf->read_uint16(bodyLen);
	int canReadSize = buf->ReadableBytes();
	if (canReadSize > 0 && bodyLen <= canReadSize)
	{
		if (buf_ == nullptr)
		{
			buf_ = std::make_shared<ByteBuffer>();
			buf_->make_writeable_bytes(bodyLen * 2);
		}
		if (buf_)
		{
			uint8 *body = buf_->GetWritePtr();
			buf->read_bytes(&body, bodyLen);
			buf_->AddWritePos(bodyLen);
		}
	}

	
	return 0;
}

int as::md::RemoteMail::WriteMailPos(ByteBufferPtr &buf, const MailPos &mailPos)
{
	buf->write_int32(mailPos.frame_id_);
	buf->write_int32(mailPos.index_);
	buf->write_int32(mailPos.page_);
	return 0;
}

int as::md::RemoteMail::ReadMailPos(ByteBufferPtr &buf, MailPos &mailPos)
{
	buf->read_int32(mailPos.frame_id_);
	buf->read_int32(mailPos.index_);
	buf->read_int32(mailPos.page_);
	return 0;
}

const uint8* as::md::RemoteMail::GetBuff()
{
	return buf_->constbegin();
}

